package gu.sql2java.json;

import java.lang.reflect.Type;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.JSONToken;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer;
import gu.sql2java.BaseBean;
import gu.sql2java.MapConverter;
import gu.sql2java.RowMetaData;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.MoreObjects.firstNonNull;

/**
 * implementation of BaseBean class for 
 * FastJson {@code com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer},<br>
 * MAVEN dependencies:
 * <pre>
 *		&lt;dependency&gt;
 *			&lt;groupId&gt;com.alibaba&lt;/groupId&gt;
 *			&lt;artifactId&gt;fastjson&lt;/artifactId&gt;
 *			&lt;version&gt;${fastjson.version}&lt;/version&gt;
 *			&lt;scope&gt;provided&lt;/scope&gt;
 *		&lt;/dependency&gt;
 * </pre>
 * 
 * @author guyadong
 *
 */
public class FastjsonDeserializer extends JavaBeanDeserializer {
	private final MapConverter<? extends BaseBean, JSONObject> converter;
	public FastjsonDeserializer(ParserConfig config, Class<? extends BaseBean> beanClass) {
		super(config, checkNotNull(beanClass,"beanClass is null"));
		converter = new MapConverter<>(beanClass, JSONObject.class);
	}
	public FastjsonDeserializer(Class<? extends BaseBean> beanClass) {
		this(ParserConfig.global, beanClass);
	}
	@SuppressWarnings("unchecked")
	@Override
	public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
		/** deserialze to JSONObject */
		JSONObject json = (JSONObject)super.deserialze(parser, JSONObject.class, fieldName);
		/** convert to BaseBean  */
		return (T) converter.fromRight(json);
	}

	@Override
	public int getFastMatchToken() {
		return JSONToken.LBRACE;
	}
	/**
	 * define FASTJSON deserializer for all class derived from BaseBean using {@link ParserConfig#global} 
	 */
	public static void install() {
		install(ParserConfig.global);
	}
	/**
	 * define FASTJSON deserializer for all class derived from BaseBean  
	 * @param config using {@link ParserConfig#global} instead of {@code null} 
	 */
	public static void install(ParserConfig config) {
		for(RowMetaData metaData:RowMetaData.allMetaDataList()){
			ParserConfig.global.putDeserializer(
					metaData.beanType,
					new FastjsonDeserializer(firstNonNull(config,ParserConfig.global),metaData.beanType));
		}
	}

}
